package com.chaoyue.media.jobhandler;


import com.chaoyue.base.constant.MediaProcessStatus;
import com.chaoyue.base.utils.Mp4VideoUtil;
import com.chaoyue.base.utils.ObjectUtils;
import com.chaoyue.media.beans.po.MediaProcess;
import com.chaoyue.media.service.MediaFileProcessService;
import com.chaoyue.media.service.MediaFileService;
import com.chaoyue.media.utils.MinioUtils;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@SuppressWarnings({"all"})
/**
 * @description: 视频处理任务类
 * @author whr
 * @date 2023/5/20 16:48
 * @version 1.0
 */
@Slf4j
@Component
public class VideoTask {
    @Autowired
    MediaFileProcessService mediaFileProcessService;
    @Autowired
    MediaFileService mediaFileService;
    @Value("${videoprocess.ffmpegpath}")
    String ffmpeg_path;

    @Autowired
    private MinioUtils minioUtils;

    @XxlJob("videoJobHandler")
    public void videoJobHandler() throws Exception {
        // 分片参数
        int shardIndex = XxlJobHelper.getShardIndex();
        int shardTotal = XxlJobHelper.getShardTotal();
        //获取cpu核心数
        int processors = Runtime.getRuntime().availableProcessors();
        //获取任务,并且任务数不超过cpu的核心数
        List<MediaProcess> mediaProcessList = mediaFileProcessService.getMediaProcessList(shardTotal, shardIndex, processors);
        int size = mediaProcessList.size();
        log.debug("任务数为:{}", size);
        if (size <= 0) {
            return;
        }
        //创建线程池
        ExecutorService threadPool = Executors.newFixedThreadPool(size);
        //创建计数器
        CountDownLatch countDownLatch = new CountDownLatch(size);
        mediaProcessList.forEach(processor -> {
            try {
                threadPool.execute(() -> {
                    Long taskId = processor.getId();
                    String fileId = processor.getFileId();
                    //开启任务
                    boolean startFlag = mediaFileProcessService.startTask(taskId);
                    if (!startFlag) {
                        return;
                    }
                    String objectName = processor.getFilePath();
                    String bucket = processor.getBucket();
                    //从minio下载视频
                    File file = minioUtils.downloadFileFromMinIO(objectName, bucket);
                    if (ObjectUtils.isEmpty(file)) {
                        log.debug("获取待处理视频失败,taskId:{},fileId{}", taskId, fileId);
                        mediaFileProcessService.saveProcessFinishStatus(taskId, "3", fileId, null, "获取待处理视频失败");
                        return;
                    }
                    //创建转码需要的临时文件
                    File mp4 = null;
                    try {
                        mp4 = File.createTempFile("minio", ".mp4");
                    } catch (IOException e) {
                        log.error("创建临时文件失败,taskId:{},错误信息:{}", taskId, e.getMessage());
                        mediaFileProcessService.saveProcessFinishStatus(taskId, MediaProcessStatus.PROCESS_FAIL.getCode(), fileId, null, "创建临时文件失败");
                        return;
                    }
                    //转码
                    String video_path = file.getAbsolutePath();
                    String mp4_name = fileId + ".mp4";
                    String mp4_path = mp4.getAbsolutePath();
                    Mp4VideoUtil videoUtil = new Mp4VideoUtil(ffmpeg_path, video_path, mp4_name, mp4_path);
                    String result = videoUtil.generateMp4();
                    if (!result.equals("success")) {
                        log.debug("视频转码失败,taskId{},fileId{}", taskId, fileId);
                        mediaFileProcessService.saveProcessFinishStatus(taskId, MediaProcessStatus.PROCESS_FAIL.getCode(), fileId, null, "视频转码失败");
                        return;
                    }
                    //上传转码文件到minio
                    String filePathByMd5 = minioUtils.getFilePathByMd5(fileId, ".mp4");
                    boolean uploadSuccess = minioUtils.addMediaFilesToMinIO(mp4.getAbsolutePath(), "vedio/mp4", bucket, filePathByMd5);
                    if (!uploadSuccess) {
                        log.debug("上传文件到minio失败,taskId{},objectName{}", taskId, filePathByMd5);
                        mediaFileProcessService.saveProcessFinishStatus(taskId, MediaProcessStatus.PROCESS_FAIL.getCode(), fileId, null, "视频上传到minio失败");
                        return;
                    }
                    String url = "/video/" + filePathByMd5;
                    mediaFileProcessService.saveProcessFinishStatus(taskId, MediaProcessStatus.PROCESS_SUCCESS.getCode(), fileId, url, null);
                });
            } finally {
                countDownLatch.countDown();
            }
        });
        countDownLatch.await();
    }
}
